package com.example.cheeseerpadmin.sys.realm;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.cheeseerpadmin.sys.common.ActiverUser;
import com.example.cheeseerpadmin.sys.common.Constant;
import com.example.cheeseerpadmin.sys.entity.SysPermission;
import com.example.cheeseerpadmin.sys.entity.SysUser;
import com.example.cheeseerpadmin.sys.service.SysPermissionService;
import com.example.cheeseerpadmin.sys.service.SysRoleService;
import com.example.cheeseerpadmin.sys.service.SysUserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

public class UserRealm extends AuthorizingRealm {

    /**
     * 特么你调用service层不使用注入注解，你调用个毛线哦
     */
    @Autowired
    @Lazy  //只有使用的时候会加载，从而确保加载之前切面已经生效了
    private SysUserService sysUserService;

    @Autowired
    @Lazy
    private SysRoleService sysRoleService;

    @Autowired
    @Lazy
    private SysPermissionService sysPermissionService;

    @Override
    public String getName() {
        return this.getClass().getSimpleName();
    }

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        /**
         * mybatisPlus自己封装的一个条件查询器
         */
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        /**
         * 从token当中获取到的一个重要的信息，然后用这个重要的信息去数据库当中查询属性字段为loginname的值，记得还要toString
         */
        queryWrapper.eq("loginname", authenticationToken.getPrincipal().toString());
        SysUser sysUser = sysUserService.getOne(queryWrapper);
        /**
         * 判断sysUser查出来以后是否为空，如果不为空，我们就进行一定的操作，将需要的信息添加到对应的对象当中并且返回
         */
        if (sysUser != null) {
            ActiverUser activerUser = new ActiverUser();
            activerUser.setUser(sysUser);

            //根据用户id去得到percode，然后存到ActiverUser当中交个授权去判断。

            QueryWrapper<SysPermission> qw = new QueryWrapper<>();
            HashSet<Integer> pids = new HashSet<>();
            List<Integer> currentRoleIds = sysUserService.queryRoleUserByUid(sysUser.getId());
            for (Integer currentRoleId : currentRoleIds) {
                List<Integer> currentPermissionIds = sysRoleService.queryRolePermissionIdsByRid(currentRoleId);
                pids.addAll(currentPermissionIds);
            }

            List<SysPermission> sysPermissionList = new ArrayList<>();
            if (pids.size() > 0) {
                qw.in("id", pids);
                qw.eq("type", Constant.TYPE_PERMISSION);
                sysPermissionList = sysPermissionService.list(qw);
            }

            List<String> percodes = new ArrayList<>();
            if (sysPermissionList != null) {
                for (SysPermission sysPermission : sysPermissionList) {
                    String percode = sysPermission.getPercode();
                    percodes.add(percode);
                }
            }
            //将得到的percode放到activerUser当中，然后交个授权去做判断
            activerUser.setPermissions(percodes);

            ByteSource credentialsSalt = ByteSource.Util.bytes(sysUser.getSalt());
            return new SimpleAuthenticationInfo(activerUser, sysUser.getPwd(), credentialsSalt, this.getName());
        }
        return null;
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //注意SimpleAuthenticationInfo()和SimpleAuthorizationInfo()是有区别的
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //然后使用PrincipalCollection得到ActiverUser，接着再从这个对象当中去获取SysUser和Permission这些信息
        ActiverUser activerUser = (ActiverUser) principalCollection.getPrimaryPrincipal();
        SysUser user = activerUser.getUser();
        List<String> permissions = activerUser.getPermissions();
        //利用得到的信息去进行判断，判断用户是不是一个超级用户，如果不是，那就要根据percode对相应的操作做出‘显隐操作’
        if (user.getType().equals(Constant.USER_TYPE_SUPER)) {
            simpleAuthorizationInfo.addStringPermission("*:*");
        } else {
            if (permissions != null && permissions.size() > 0) {
                simpleAuthorizationInfo.addStringPermissions(permissions);
            }
        }
        return simpleAuthorizationInfo;
    }

}
